import { SERVER_DATA_CODE } from "../consts/Consts";
import { globlData } from "../globData/GloblData";
import { SingletonTemplet } from "../utils/SingletonTemplet";


/**
 * http请求接口类型
 */
export enum HttpMethod {
    GET  = "GET",
    POST = "POST",
}
export class HttpRequestImp implements HttpRequest{
    api: string = "";
    params: any = null;
    needToken?: boolean | undefined;
    method: HttpMethod = HttpMethod.POST;
    
    
}
/**
 * http请求封装
 */
interface HttpRequest{
	api: string,
	params: any,
	needToken?: boolean,
	method: HttpMethod
}

/**
 * http请求回调
 */
interface HttpCallback{
	onSuccess: SuccessCallback
	onServerError: ErrorCallback
	onNetworkError: ErrorCallback
}
/**
 * 请求错误
 */
interface HttpError{
	code: number,
	msg: string
}
/**
 *  成功回调 callback方法定义
 */
type SuccessCallback = (data: string  | ArrayBuffer | AnyObject) => Promise<any>;
/**
 *  错误的callback方法定义
 */
type ErrorCallback = (error: HttpError) => void;

/**
 * 服务器返回错误
*/
class ServerError implements HttpError{
	code: number
	msg: string
	constructor(code:number, msg:string){
		this.code = code;
		this.msg = msg;
	}
	//网络请求错误处理
	processError(){
		//这里根据code显示不同的错误提示信息
		if(this.code == SERVER_DATA_CODE.TOKEN_ERROR){
			this.processUnauthError()
		}else if(this.code >= SERVER_DATA_CODE.HTTPINNERERR){
			this.processServerError()
		}else{
			this.processUnknownError()
		}
	}
	//处理未认证错误
	async processUnauthError(){
	   return uni.showToast({
			title: this.msg ?this.msg :"认证失效",
			icon: "none",
			duration: 3000
		})
	}
	//处理服务器返回错误
	async  processServerError(){
		return uni.showToast({
			title: this.msg ? this.msg : "服务器返回错误",
			icon: "none",
			duration: 3000
		})
	}
	//处理未知错误
	async processUnknownError(){
	   return uni.showToast({
			title: this.msg ? this.msg:"未知错误",
			icon: "none"
		})
	}
}
//默认网络拦截器
class HttpInterceptor{
	private readonly CODE_SUCCESS: number = 200;
	public constructor(){
		
	}
	handleResponse(statusCode: number,data: string  | ArrayBuffer | AnyObject){
		let error: ServerError;
		if(statusCode == this.CODE_SUCCESS){
			return data;
		}else{
			error = new ServerError(statusCode, data as string)
			error.processError();
			throw error;
		}
		
	}
}
/**
 * http 接口访问工具
 */
export class  HttpUtil extends SingletonTemplet{
	public method: HttpMethod = HttpMethod.POST;
	public showLoading: boolean = true;
	public loadingText: string = '请求中...';
	public loadingTime: number = 800; //单位 ms毫秒
	public originalData: boolean = false; // 是否在拦截器中返回服务端的原始数据
	public loadingMask: boolean = false; //展示loading的时候，是否给一个透明的蒙层，防止触摸穿透
	public header = { 'content-type': 'application/x-www-form-urlencoded','token':localStorage.getItem('token') }; // 配置请求头信息
	private m_Interceprot: HttpInterceptor;
	constructor(){
		super();
		this.m_Interceprot = new HttpInterceptor();
	}
	/**
	 * http配置设置
	 */
    public setConfig(opts: {
		method: HttpMethod;
		showLoading?: boolean;
		loadingText?: string;
		loadingTime?: number;
		originalData?: boolean;
		loadingMask?: boolean;
		header?: any;
	}) {
		this.method = opts.method;
		this.showLoading = opts.showLoading?opts.showLoading:this.showLoading;
		this.loadingText = opts.loadingText?opts.loadingText:this.loadingText;
		this.loadingTime = opts.loadingTime?opts.loadingTime:this.loadingTime;
		this.originalData = opts.originalData?opts.originalData:this.originalData;
		this.loadingMask = opts.loadingMask?opts.loadingMask:this.loadingMask;
		this.header = opts.header?opts.header:this.header;
	}
	/**
	 * 网络请求方式
	 * @param api string 接口地址
	 * @param method HttpMethod  请求参数
	 * @param params string | AnyObject | ArrayBuffer 请求参数
	 * */
    async request(api: string = "",method:HttpMethod =HttpMethod.GET,params?:string | AnyObject | ArrayBuffer):Promise<any>{
		return await new Promise((resolve,reject)=>{
			uni.request({
				url: globlData.getAppHttpHost() + api,
				data: params,
				method: method?method:this.method,
				header:this.header,
				success: result => {
					let interceprotData = this.m_Interceprot.handleResponse(result.statusCode, result.data)
					return resolve(interceprotData);
				},
				fail: reason => {
				   return reject(reason.errMsg);
				}
			})
		})
		
	 }	
	requestAsyn(api: string = "",method:HttpMethod =HttpMethod.GET,params?:string | AnyObject | ArrayBuffer,cb?:Function){
	 	uni.request({
	 		url: globlData.getAppHttpHost() + api,
	 		data: params,
	 		method: method?method:this.method,
	 		header:this.header,
	 		success: result => {
				// let interceprotData = this.m_Interceprot.handleResponse(result.statusCode, result.data)
	 			!!cb && cb(false,result.data);
	 		},
	 		fail: reason => {
	 			uni.showToast({
	 				title: reason.errMsg,
	 				icon: "none",
	 				duration: 3000
	 			})
	 		   !!cb && cb(false);
	 		}
	 	})
	  }	
}
export const httpUtil = HttpUtil.getInstance();